## 一、创建 vue3 项目
[Vite](https://so.csdn.net/so/search?q=Vite&spm=1001.2101.3001.7020)是一种新型前端构建工具,能够显著提升前端开发体验。
1、 在需要创建项目的目录下打开 cmd,并输入以下命令:
npm create vite@latest
2、 之后根据自己所需按照提示操作即可,这里是使用 ts 创建 vue3 项目。
3、 随后使用 vs code 打开项目执行对应命令即可完成项目的创建。
## 二、修改配置文件
这里我们需要注意到 `vite.config.ts` 这个配置文件,之后我们的配置都会写在这里。
```
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
// 基本路径
base: './',
plugins: [
vue()
],
resolve: {
// src 别名配置
alias: {
"@": resolve(__dirname, 'src'),
},
// 使用路径别名时想要省略的后缀名,可以自己增减
extensions: ['.js', '.json', '.ts']
},
server: {
// 端口号
port: 8080,
// 监听所有地址
host: '0.0.0.0',
// 服务启动时是否自动打开浏览器
open: true,
// 允许跨域
cors: true,
// 自定义代理规则
proxy: {},
},
build: {
// 设置最终构建的浏览器兼容目标
target: 'es2015',
// 构建后是否生成 source map 文件
sourcemap: false,
// chunk 大小警告的限制(以 kbs 为单位)
chunkSizeWarningLimit: 2000,
// 启用/禁用 gzip 压缩大小报告
reportCompressedSize: false,
},
})
```
在 ts 中,可能会提示找不到 path,可执行以下命令安装:pnpm install @types/node --save-dev
**别名配置**:
在 `tsconfig.json` 中加入配置
```
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
/* 别名配置 */
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
],
},
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"references": [
{
"path": "./tsconfig.node.json"
}
],
}
```
之后即可通过@来代指src目录了。
## 三、安装 router
1、 在项目目录的控制台中输入命令安装 router:pnpm install vue-router@4
2、 为了方便测试,先在 src 目录下创建 views 目录,并在 views 目录下创建 index.vue 和 about.vue 文件
index.vue
```
<template>
<div>
<h1>这是主页!</h1>
<button @click="to">前往</button>
</div>
</template>
<script setup>
import { router } from '@/router';
function to() {
router.push('/about')
}
</script>
```
about.vue
```
<template>
<div>
<h1>这是关于页!</h1>
<button @click="to">前往</button>
</div>
</template>
<script setup>
import { router } from '@/router';
function to() {
router.push('/')
}
</script>
```
3、 随后在 src 目录下创建目录 router,并在 router 目录下创建 index.ts 文件。
```
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = [
{
path: "/",
component: () => import("@/views/index.vue")
},
{
path: "/about",
component: () => import("@/views/about.vue")
},
];
export const router = createRouter({
history: createWebHistory(),
routes,
});
```
4、 在 `main.ts` 中引入
```
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { router } from './router/index'
createApp(App)
.use(router)
.mount('#app')
```
5、 最后修改 `App.vue` 文件
```
<script setup>
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView></RouterView>
</template>
<style scoped>
</style>
```
## 四、引入 element plus
1、 引入依赖
pnpm install element-plus
2、全局引入
在 `main.ts` 中引入
```
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App)
.use(ElementPlus)
.mount('#app')
```
## 五、添加环境变量
1、 在与 src 同级目录下分别创建`.env.development` 和`.env.production` 文件
.env.development
```
VITE_USER_NODE_ENV=dev
VITE_PARAM=dev
VITE_BASE_URL="http://localhost:8081/v1/api"
```
.env.production
```
VITE_USER_NODE_ENV=prod
VITE_PARAM=prod
VITE_BASE_URL='https://api.example.com/v1/api'
```
需要注意的是,`VITE_` 前缀是必须要有的,否则会获取不到
2、使用
```
import.meta.env.变量
// 例如
import.meta.env.VITE_BASE_URL
```
## 六、引入 axios
1、引入 axios
pnpm install axios
2、封装统一请求
在 src 目录下新建 utils 目录,然后在 utils 目录下创建 `request.ts`
```
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios"
import { ElMessage } from 'element-plus'
// 创建 axios 实例
const request = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
timeout: 10000,
headers: { "Content-Type": "application/json;charset=utf-8" },
});
// 请求拦截器
request.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = window.sessionStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error: any) => {
return Promise.reject(error)
}
);
// 响应拦截器
request.interceptors.response.use(
(response: AxiosResponse) => {
const data = response.data;
if (data.code === 200) {
return response.data;
}
ElMessage.error(data.msg || "系统出错");
return Promise.reject(new Error(data.msg || "Error"));
},
(error: any) => {
if (error.response.data) {
ElMessage.error(error.response.data.msg || "系统出错");
}
return Promise.reject(error.message);
}
);
// 导出 axios 实例
export default request;
```
4、编写 api 请求
在 src 下创建 api 目录,定义一个 page 对象,用于接收分页返回来的数据
page.ts
```
export interface Page<T> {
records: Array<T>,
total: number,
}
```
在 api 下创建 test 目录,并创建 test.ts 和 types.ts 文件
test.ts
```
import request from "@/utils/request"
import { AxiosPromise } from "axios";
import { HotArticleQuery, HotArticleVo } from './types'
import { Page } from "../page";
// 入参是HotArticleQuery,返回体是Page<HotArticleVo>
export function getArticleApi(queryParams?: HotArticleQuery) : AxiosPromise<Page<HotArticleVo>> {
return request({
url: '/article/list',
method: 'post',
data: queryParams
})
}
```
types.ts
```
// 请求参数
export interface HotArticleQuery {
pageSize: number;
pageIndex: number;
searchKey: string;
}
// 返回分页数据的具体参数
export interface HotArticleVo {
id: number;
title: string;
}
```
调用
```
<template>
<div>
<h1>这是主页!</h1>
<el-button @click="to">前往</el-button>
<el-button @click="getArticleList">获取</el-button>
</div>
</template>
<script setup>
import { getArticleApi } from '@/api/test/test'
import { HotArticleQuery, HotArticleVo } from '@/api/test/types'
import { Page } from '@/api/page'
import { router } from '@/router';
import { reactive, ref } from 'vue';
const query = reactive<HotArticleQuery>({
pageIndex: 1,
pageSize: 10,
searchKey: ''
})
const articleData = ref<Page<HotArticleVo>>();
function getArticleList() {
getArticleApi(query).then(res => {
articleData.value = res.data
console.log(articleData.value.records)
console.log(articleData.value.total)
})
}
function to() {
router.push('/about')
}
</script>
```
## 七、状态管理 Pinia
1、安装pnpm install pinia
2、在 main.ts 中引入
```
import { createPinia } from "pinia";
const pinia = createPinia();
createApp(App)
.use(pinia)
.mount('#app')
```
3、创建 store
在 src 目录下创建 store 目录,然后创建一个 user.ts 用于存放用户相关数据
```
import { defineStore } from 'pinia'
// 第一个参数是应用程序中 store 的唯一 id
export const useUsersStore = defineStore('users', {
// 配置项
state: () => {
// 这里假设有一些参数
return {
uid: 1,
username: 'admin',
exp: 100
}
}
})
```
4、使用 store
```
<el-button @click="get">测试pinia</el-button>
import { useUsersStore } from '@/store/user'
function get() {
const store = useUsersStore()
console.log(store)
// 或者
const { uid, username, exp} = useUsersStore()
console.log(uid)
console.log(username)
console.log(exp)
// 修改
store.exp = 200
// 重置
store.$reset()
console.log(store)
}
```
5、getter
在 user.ts 中定义一个 getters
```
import { defineStore } from 'pinia'
// 第一个参数是应用程序中 store 的唯一 id
export const useUsersStore = defineStore('users', {
// 配置项
state: () => {
return {
uid: 1,
username: 'admin',
exp: 100
}
},
getters: {
// 无参
addExp: (state) => {
return state.exp + 150
},
// 带参
addExpCustom: (state) => {
return (num: number) => state.exp + num
}
}
})
```
使用
```
console.log(store.addExp)
console.log(store.addExpCustom(180))
```
6、actions 属性
actions 属性类似于一个方法,我们可以在里面进行业务操作,例如发送请求等
```
export const useUsersStore = defineStore('users', {
// 配置项
state: () => {
return {
uid: 1,
username: 'admin',
exp: 100
}
},
getters: {
addExp: (state) => {
return state.exp + 150
},
addExpCustom: (state) => {
return (num: number) => state.exp + num
}
},
actions: {
showParam(param: string) {
console.log('传入的参数为:' + param)
}
}
})
```
使用
```
store.showParam('test')
```
微信公众号
业务咨询:400-9969-069(24小时服务) 028-86052918
售后热线:028-86052836
公司地址:成都市武侯区天益街38号理想中心3栋1810